// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie;

import java.util.ArrayList;
import java.util.HashMap;
import zombie.audio.BaseSoundEmitter;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.characters.BodyDamage.BodyDamage;
import zombie.core.Core;
import zombie.core.SpriteRenderer;
import zombie.debug.DebugLog;
import zombie.iso.IsoChunk;
import zombie.iso.IsoChunkMap;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoUtils;
import zombie.iso.IsoWorld;
import zombie.iso.areas.IsoBuilding;

public final class FliesSound {
    public static final zombie.FliesSound instance = new zombie.FliesSound();
    private static final IsoGridSquare[] tempSquares = new IsoGridSquare[100];
    private final zombie.FliesSound.PlayerData[] playerData = new zombie.FliesSound.PlayerData[4];
    private final ArrayList<zombie.FliesSound.FadeEmitter> fadeEmitters = new ArrayList();
    private float fliesVolume = -1.0F;

    public FliesSound() {
        for (int _int = 0; _int < this.playerData.length; _int++) {
            this.playerData[_int] = new zombie.FliesSound.PlayerData();
        }
    }

    public void Reset() {
        for (int _int = 0; _int < this.playerData.length; _int++) {
            this.playerData[_int].Reset();
        }
    }

    public void update() {
        if (zombie.SandboxOptions.instance.DecayingCorpseHealthImpact.getValue() != 1) {
            for (int int0 = 0; int0 < IsoPlayer.numPlayers; int0++) {
                IsoPlayer isoPlayer = IsoPlayer.players[int0];
                if (isoPlayer != null && isoPlayer.getCurrentSquare() != null) {
                    this.playerData[int0].update(isoPlayer);
                }
            }

            for (int int1 = 0; int1 < this.fadeEmitters.size(); int1++) {
                zombie.FliesSound.FadeEmitter fadeEmitter = (zombie.FliesSound.FadeEmitter)this.fadeEmitters.get(int1);
                if (fadeEmitter.update()) {
                    this.fadeEmitters.remove(int1--);
                }
            }
        }
    }

    public void render() {
        IsoChunkMap isoChunkMap = IsoWorld.instance.CurrentCell.ChunkMap[0];

        for (int int0 = 0; int0 < IsoChunkMap.ChunkGridWidth; int0++) {
            for (int int1 = 0; int1 < IsoChunkMap.ChunkGridWidth; int1++) {
                IsoChunk isoChunk = isoChunkMap.getChunk(int1, int0);
                if (isoChunk != null) {
                    zombie.FliesSound.ChunkData chunkData = isoChunk.corpseData;
                    if (chunkData != null) {
                        int int2 = (int)IsoPlayer.players[0].z;
                        zombie.FliesSound.ChunkLevelData chunkLevelData = chunkData.levelData[int2];

                        for (int int3 = 0; int3 < chunkLevelData.emitters.length; int3++) {
                            zombie.FliesSound.FadeEmitter fadeEmitter = chunkLevelData.emitters[int3];
                            if (fadeEmitter != null && fadeEmitter.emitter != null) {
                                this.paintSquare(fadeEmitter.sq.x, fadeEmitter.sq.y, fadeEmitter.sq.z, 0.0F, 1.0F, 0.0F, 1.0F);
                            }

                            if (chunkLevelData.refCount[int3] > 0) {
                                this.paintSquare(isoChunk.wx * 10 + 5, isoChunk.wy * 10 + 5, 0, 0.0F, 0.0F, 1.0F, 1.0F);
                            }
                        }

                        IsoBuilding isoBuilding = IsoPlayer.players[0].getCurrentBuilding();
                        if (isoBuilding != null && chunkLevelData.buildingCorpseCount != null && chunkLevelData.buildingCorpseCount.containsKey(isoBuilding)) {
                            this.paintSquare(isoChunk.wx * 10 + 5, isoChunk.wy * 10 + 5, int2, 1.0F, 0.0F, 0.0F, 1.0F);
                        }
                    }
                }
            }
        }
    }

    private void paintSquare(int int4, int int3, int int2, float float0, float float1, float float2, float float3) {
        int int0 = Core.TileScale;
        int int1 = (int)IsoUtils.XToScreenExact((float)int4, (float)(int3 + 1), (float)int2, 0);
        int int5 = (int)IsoUtils.YToScreenExact((float)int4, (float)(int3 + 1), (float)int2, 0);
        SpriteRenderer.instance
            .renderPoly(
                (float)int1,
                (float)int5,
                (float)(int1 + 32 * int0),
                (float)(int5 - 16 * int0),
                (float)(int1 + 64 * int0),
                (float)int5,
                (float)(int1 + 32 * int0),
                (float)(int5 + 16 * int0),
                float0,
                float1,
                float2,
                float3
            );
    }

    public void chunkLoaded(IsoChunk chunk) {
        if (chunk.corpseData == null) {
            chunk.corpseData = new zombie.FliesSound.ChunkData(chunk.wx, chunk.wy);
        }

        chunk.corpseData.wx = chunk.wx;
        chunk.corpseData.wy = chunk.wy;
        chunk.corpseData.Reset();
    }

    public void corpseAdded(int x, int y, int z) {
        if (z >= 0 && z < 8) {
            zombie.FliesSound.ChunkData chunkData = this.getChunkData(x, y);
            if (chunkData != null) {
                chunkData.corpseAdded(x, y, z);

                for (int _int = 0; _int < this.playerData.length; _int++) {
                    if (chunkData.levelData[z].refCount[_int] > 0) {
                        this.playerData[_int].forceUpdate = true;
                    }
                }
            }
        } else {
            DebugLog.General.error("invalid z-coordinate %d,%d,%d", x, y, z);
        }
    }

    public void corpseRemoved(int x, int y, int z) {
        if (z >= 0 && z < 8) {
            zombie.FliesSound.ChunkData chunkData = this.getChunkData(x, y);
            if (chunkData != null) {
                chunkData.corpseRemoved(x, y, z);

                for (int _int = 0; _int < this.playerData.length; _int++) {
                    if (chunkData.levelData[z].refCount[_int] > 0) {
                        this.playerData[_int].forceUpdate = true;
                    }
                }
            }
        } else {
            DebugLog.General.error("invalid z-coordinate %d,%d,%d", x, y, z);
        }
    }

    public int getCorpseCount(IsoGameCharacter chr) {
        return chr != null && chr.getCurrentSquare() != null
            ? this.getCorpseCount((int)chr.getX() / 10, (int)chr.getY() / 10, (int)chr.getZ(), chr.getBuilding())
            : 0;
    }

    private int getCorpseCount(int int4, int int3, int int5, IsoBuilding isoBuilding) {
        int int0 = 0;

        for (int int1 = -1; int1 <= 1; int1++) {
            for (int int2 = -1; int2 <= 1; int2++) {
                zombie.FliesSound.ChunkData chunkData = this.getChunkData((int4 + int2) * 10, (int3 + int1) * 10);
                if (chunkData != null) {
                    zombie.FliesSound.ChunkLevelData chunkLevelData = chunkData.levelData[int5];
                    if (isoBuilding == null) {
                        int0 += chunkLevelData.corpseCount;
                    } else if (chunkLevelData.buildingCorpseCount != null) {
                        Integer integer = (Integer)chunkLevelData.buildingCorpseCount.get(isoBuilding);
                        if (integer != null) {
                            int0 += integer;
                        }
                    }
                }
            }
        }

        return int0;
    }

    private zombie.FliesSound.ChunkData getChunkData(int int0, int int1) {
        IsoChunk isoChunk = IsoWorld.instance.CurrentCell.getChunkForGridSquare(int0, int1, 0);
        return isoChunk != null ? isoChunk.corpseData : null;
    }

    public class ChunkData {
        private int wx;
        private int wy;
        private final zombie.FliesSound.ChunkLevelData[] levelData = new zombie.FliesSound.ChunkLevelData[8];

        private ChunkData(int int0, int int1) {
            this.wx = int0;
            this.wy = int1;

            for (int int2 = 0; int2 < this.levelData.length; int2++) {
                this.levelData[int2] = FliesSound.this.new ChunkLevelData();
            }
        }

        private void corpseAdded(int int0, int int1, int int2) {
            IsoGridSquare isoGridSquare = IsoWorld.instance.CurrentCell.getGridSquare(int0, int1, int2);
            IsoBuilding isoBuilding = isoGridSquare == null ? null : isoGridSquare.getBuilding();
            int int3 = int0 - this.wx * 10;
            int int4 = int1 - this.wy * 10;
            this.levelData[int2].corpseAdded(int3, int4, isoBuilding);
        }

        private void corpseRemoved(int int0, int int1, int int2) {
            IsoGridSquare isoGridSquare = IsoWorld.instance.CurrentCell.getGridSquare(int0, int1, int2);
            IsoBuilding isoBuilding = isoGridSquare == null ? null : isoGridSquare.getBuilding();
            int int3 = int0 - this.wx * 10;
            int int4 = int1 - this.wy * 10;
            this.levelData[int2].corpseRemoved(int3, int4, isoBuilding);
        }

        private void Reset() {
            for (int _int = 0; _int < this.levelData.length; _int++) {
                this.levelData[_int].Reset();
            }
        }
    }

    private class ChunkLevelData {
        int corpseCount = 0;
        HashMap<IsoBuilding, Integer> buildingCorpseCount = null;
        final int[] refCount = new int[4];
        final zombie.FliesSound.FadeEmitter[] emitters = new zombie.FliesSound.FadeEmitter[4];

        ChunkLevelData() {
        }

        void corpseAdded(int var1, int var2, IsoBuilding isoBuilding) {
            if (isoBuilding == null) {
                this.corpseCount++;
            } else {
                if (this.buildingCorpseCount == null) {
                    this.buildingCorpseCount = new HashMap();
                }

                Integer integer = (Integer)this.buildingCorpseCount.get(isoBuilding);
                if (integer == null) {
                    this.buildingCorpseCount.put(isoBuilding, 1);
                } else {
                    this.buildingCorpseCount.put(isoBuilding, integer + 1);
                }
            }
        }

        void corpseRemoved(int var1, int var2, IsoBuilding isoBuilding) {
            if (isoBuilding == null) {
                this.corpseCount--;
            } else if (this.buildingCorpseCount != null) {
                Integer integer = (Integer)this.buildingCorpseCount.get(isoBuilding);
                if (integer != null) {
                    if (integer > 1) {
                        this.buildingCorpseCount.put(isoBuilding, integer - 1);
                    } else {
                        this.buildingCorpseCount.remove(isoBuilding);
                    }
                }
            }
        }

        IsoGridSquare calcSoundPos(int int2, int int1, int int0, IsoBuilding isoBuilding) {
            IsoChunk isoChunk = IsoWorld.instance.CurrentCell.getChunkForGridSquare(int2 * 10, int1 * 10, int0);
            if (isoChunk == null) {
                return null;
            } else {
                int int3 = 0;

                for (int int4 = 0; int4 < 10; int4++) {
                    for (int int5 = 0; int5 < 10; int5++) {
                        IsoGridSquare isoGridSquare = isoChunk.getGridSquare(int5, int4, int0);
                        if (isoGridSquare != null && !isoGridSquare.getStaticMovingObjects().isEmpty() && isoGridSquare.getBuilding() == isoBuilding) {
                            zombie.FliesSound.tempSquares[int3++] = isoGridSquare;
                        }
                    }
                }

                return int3 > 0 ? zombie.FliesSound.tempSquares[int3 / 2] : null;
            }
        }

        void update(int int1, int int2, int int3, IsoPlayer isoPlayer) {
            this.refCount[isoPlayer.PlayerIndex]++;
            int int0 = FliesSound.this.getCorpseCount(int1, int2, int3, isoPlayer.getCurrentBuilding());
            if ((double)BodyDamage.getSicknessFromCorpsesRate(int0) > zombie.ZomboidGlobals.FoodSicknessDecrease) {
                IsoBuilding isoBuilding = isoPlayer.getCurrentBuilding();
                IsoGridSquare isoGridSquare = this.calcSoundPos(int1, int2, int3, isoBuilding);
                if (isoGridSquare == null) {
                    return;
                }

                if (this.emitters[isoPlayer.PlayerIndex] == null) {
                    this.emitters[isoPlayer.PlayerIndex] = FliesSound.this.new FadeEmitter();
                }

                zombie.FliesSound.FadeEmitter fadeEmitter0 = this.emitters[isoPlayer.PlayerIndex];
                if (fadeEmitter0.emitter == null) {
                    fadeEmitter0.emitter = IsoWorld.instance.getFreeEmitter((float)isoGridSquare.x, (float)isoGridSquare.y, (float)int3);
                    fadeEmitter0.emitter.playSoundLoopedImpl("CorpseFlies");
                    fadeEmitter0.emitter.setVolumeAll(0.0F);
                    fadeEmitter0.volume = 0.0F;
                    FliesSound.this.fadeEmitters.add(fadeEmitter0);
                } else {
                    fadeEmitter0.sq.setHasFlies(false);
                    fadeEmitter0.emitter.setPos((float)isoGridSquare.x, (float)isoGridSquare.y, (float)int3);
                    if (fadeEmitter0.targetVolume != 1.0F && !FliesSound.this.fadeEmitters.contains(fadeEmitter0)) {
                        FliesSound.this.fadeEmitters.add(fadeEmitter0);
                    }
                }

                fadeEmitter0.targetVolume = 1.0F;
                fadeEmitter0.sq = isoGridSquare;
                isoGridSquare.setHasFlies(true);
            } else {
                zombie.FliesSound.FadeEmitter fadeEmitter1 = this.emitters[isoPlayer.PlayerIndex];
                if (fadeEmitter1 != null && fadeEmitter1.emitter != null) {
                    if (!FliesSound.this.fadeEmitters.contains(fadeEmitter1)) {
                        FliesSound.this.fadeEmitters.add(fadeEmitter1);
                    }

                    fadeEmitter1.targetVolume = 0.0F;
                    fadeEmitter1.sq.setHasFlies(false);
                }
            }
        }

        void deref(IsoPlayer isoPlayer) {
            int _int = isoPlayer.PlayerIndex;
            this.refCount[_int]--;
            if (this.refCount[_int] <= 0) {
                if (this.emitters[_int] != null && this.emitters[_int].emitter != null) {
                    if (!FliesSound.this.fadeEmitters.contains(this.emitters[_int])) {
                        FliesSound.this.fadeEmitters.add(this.emitters[_int]);
                    }

                    this.emitters[_int].targetVolume = 0.0F;
                    this.emitters[_int].sq.setHasFlies(false);
                }
            }
        }

        void Reset() {
            this.corpseCount = 0;
            if (this.buildingCorpseCount != null) {
                this.buildingCorpseCount.clear();
            }

            for (int _int = 0; _int < 4; _int++) {
                this.refCount[_int] = 0;
                if (this.emitters[_int] != null) {
                    this.emitters[_int].Reset();
                }
            }
        }
    }

    private class FadeEmitter {
        private static final float FADE_IN_RATE = 0.01F;
        private static final float FADE_OUT_RATE = -0.01F;
        BaseSoundEmitter emitter = null;
        float volume = 1.0F;
        float targetVolume = 1.0F;
        IsoGridSquare sq = null;

        boolean update() {
            if (this.emitter == null) {
                return true;
            } else {
                if (this.volume < this.targetVolume) {
                    this.volume = this.volume + 0.01F * (zombie.GameTime.getInstance().getMultiplier() / 1.6F);
                    if (this.volume >= this.targetVolume) {
                        this.volume = this.targetVolume;
                        return true;
                    }
                } else {
                    this.volume = this.volume + -0.01F * (zombie.GameTime.getInstance().getMultiplier() / 1.6F);
                    if (this.volume <= 0.0F) {
                        this.volume = 0.0F;
                        this.emitter.stopAll();
                        this.emitter = null;
                        return true;
                    }
                }

                this.emitter.setVolumeAll(this.volume);
                return false;
            }
        }

        void Reset() {
            this.emitter = null;
            this.volume = 1.0F;
            this.targetVolume = 1.0F;
            this.sq = null;
        }
    }

    private class PlayerData {
        int wx = -1;
        int wy = -1;
        int z = -1;
        IsoBuilding building = null;
        boolean forceUpdate = false;

        PlayerData() {
        }

        boolean isSameLocation(IsoPlayer isoPlayer) {
            IsoGridSquare isoGridSquare = isoPlayer.getCurrentSquare();
            return isoGridSquare != null && isoGridSquare.getBuilding() != this.building
                ? false
                : (int)isoPlayer.getX() / 10 == this.wx && (int)isoPlayer.getY() / 10 == this.wy && (int)isoPlayer.getZ() == this.z;
        }

        void update(IsoPlayer isoPlayer) {
            if (this.forceUpdate || !this.isSameLocation(isoPlayer)) {
                this.forceUpdate = false;
                int int0 = this.wx;
                int int1 = this.wy;
                int int2 = this.z;
                IsoGridSquare isoGridSquare = isoPlayer.getCurrentSquare();
                this.wx = isoGridSquare.getX() / 10;
                this.wy = isoGridSquare.getY() / 10;
                this.z = isoGridSquare.getZ();
                this.building = isoGridSquare.getBuilding();

                for (int int3 = -1; int3 <= 1; int3++) {
                    for (int int4 = -1; int4 <= 1; int4++) {
                        zombie.FliesSound.ChunkData chunkData0 = FliesSound.this.getChunkData((this.wx + int4) * 10, (this.wy + int3) * 10);
                        if (chunkData0 != null) {
                            zombie.FliesSound.ChunkLevelData chunkLevelData0 = chunkData0.levelData[this.z];
                            chunkLevelData0.update(this.wx + int4, this.wy + int3, this.z, isoPlayer);
                        }
                    }
                }

                if (int2 != -1) {
                    for (int int5 = -1; int5 <= 1; int5++) {
                        for (int int6 = -1; int6 <= 1; int6++) {
                            zombie.FliesSound.ChunkData chunkData1 = FliesSound.this.getChunkData((int0 + int6) * 10, (int1 + int5) * 10);
                            if (chunkData1 != null) {
                                zombie.FliesSound.ChunkLevelData chunkLevelData1 = chunkData1.levelData[int2];
                                chunkLevelData1.deref(isoPlayer);
                            }
                        }
                    }
                }
            }
        }

        void Reset() {
            this.wx = this.wy = this.z = -1;
            this.building = null;
            this.forceUpdate = false;
        }
    }
}
